<?php

namespace Muyuxuanpay\threePay\src\hk;

use GuzzleHttp\Client;

trait CommonTrait
{
    protected $URL = [
        'wx_pub'     => 'http://preposition.hkrt.cn:4430/api/polymeric/pay',
        'merchant'   => 'http://preposition.hkrt.cn:4430/api/polymeric/pay',
        'alipay_wap' => 'http://preposition.hkrt.cn:4430/api/polymeric/pay',
        'wx_scan'    => 'http://preposition.hkrt.cn:4430/api/polymeric/pay',
    ];

    protected $RESULT_CODE_SUCCESS = '0000';

    /** @var string 交易等待中 */
    protected $RESULT_CODE_PINGAN = '9999';
    //sdk相关
    protected function getEncryptionRequestBody(array $data, string $certificate):string{
        $certificate = sprintf("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", $certificate);

        $publicKey = openssl_get_publickey($certificate);
        if ($publicKey === false) {
            throw new \Exception('解析密钥失败');
        }
        //证书详情
        if(empty($data)){
            $jsonData = "{}";
        }else{
            $jsonData = json_encode($data);
        }
        //分割字符串加密
        $encrypt = '';
        foreach (str_split($jsonData, 117) as $str) {
            if (!openssl_public_encrypt($str, $encryptItem, $publicKey)) {
                throw new \Exception("报文签名失败");
            }
            $encrypt .= $encryptItem;
        }

        return base64_encode($encrypt);
    }
    /**
     * 报文签名
     * @param array $data
     * @param string $certificate
     * @return string
     * @throws \Exception
     */
    protected function getSign(array $data,$certificate=''): string
    {
        if(empty($certificate)){
            $certificate = $this->config['private_key'];
        }
        $certificate = sprintf("-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----", wordwrap($certificate, 64, "\n", true));
        $encrypt = '';
        $signStr = $this->toSignStr($data);

        $privateKey = openssl_get_privatekey($certificate);

        if ($privateKey === false) {
            throw new \Exception('解析密钥失败');
        }
        if (!openssl_sign($signStr, $encrypt, $privateKey, "SHA256")) {
            throw new \Exception('报文签名失败');
        }
        return base64_encode($encrypt);
    }

    //biz_content加密参数按格式组装
    protected function toSignStr($values)
    {
        $buff = '';
        foreach ($values as $key => $value) {
            if(!empty($value)){
                $buff .= $key . '=' . $value . '&';
            }
        }
        return trim($buff, '&');
    }

    //RSA2全局返参解密
    public function rsaDecrypt($content,$certificate=''){
        if(empty($certificate)){
            $certificate = $this->config['private_key'];
        }
        $certificate = sprintf("-----BEGIN RSA PRIVATE KEY-----\n%s\n-----END RSA PRIVATE KEY-----", wordwrap($certificate, 64, "\n", true));
        $encrypt = '';

        $privateKey = openssl_get_privatekey($certificate);

        if ($privateKey === false) {
            throw new \Exception('解析密钥失败');
        }

        $decrypted = '';
        foreach (str_split(base64_decode($content), 256) as $chunk) {
            if (!openssl_private_decrypt($chunk, $decryptData, $privateKey, OPENSSL_PKCS1_PADDING)) {
                throw new \Exception("报文解密失败");
            }
            $decrypted .= $decryptData;
        }

        return $decrypted;
    }
    //解密码时把转换后的符号替换特殊符号
    protected function urlsafe_b64decode($string) {
        $data = str_replace(array('-','_'),array('+','/'),$string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }

    protected function post(string $url, $data)
    {
        $obj = new Client();

        // echo "<pre>";
        // print_r($url);
        // echo "<pre>";
        // print_r(json_encode($data));
        // exit;

        $response = $obj->post($url,[
            'headers' => [
                'Content-Type' => 'application/json',
                'charset'      => 'UTF-8',
            ],
            'body' => json_encode($data),
        ]);
        if ($response->getStatusCode() != 200) {
            throw new \Exception('请求失败,服务器返回状态码:' . $response->getStatusCode());
        }
        $responseContent = $response->getBody()->getContents();
        //  echo "<pre>";
        // print_r($responseContent);
        // exit;
        if(empty($responseContent)){
            throw new \Exception('请求失败,服务器返回状态码:' . $response->getStatusCode());
        }
        $responseContent = json_decode($responseContent, true);
        if($responseContent==''||$responseContent==null){
            throw new \Exception('请求失败,服务器返回状态码:' . $response->getStatusCode());
        }

        if($responseContent['return_code']!='10000'){
            throw new \Exception($responseContent['return_msg']??"无返回消息");
        }
        $resultDecrypt = $this->rsaDecrypt($responseContent['sign'], $this->config['private_key']);
        if(empty($resultDecrypt)){
            throw new \Exception('解密失败');
        }
        $responseContent['content'] = json_decode($resultDecrypt, true);
        if(is_string($responseContent['content'])){
            $responseContent['content'] = json_decode($responseContent['content'], true);
        }
        return $responseContent;
    }

    protected function generateOrderNo(): string
    {
        return md5(uniqid('M') . substr(microtime(true), -3));
    }

    public function backSuccess()
    {
        return [
            'return_code'=>'SUCCESS',
            'return_msg'=>'OK',
        ];
    }
    public function backFail()
    {
        return [
            'return_code'=>'FAIL',
            'return_msg'=>'FAIL',
        ];
    }
}